/*
 *
 *  This library is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License as
 *  published by the Free Software Foundation; either version 2.1 of
 *  the License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *  Copyright (C) 2015 Intel Corporation
 *
 */

#ifndef __ALSA_TOPOLOGY_H
#define __ALSA_TOPOLOGY_H

#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

/**
 * \defgroup topology Topology Interface
 * \{
 */

/*! \page topology ALSA Topology Interface
 *
 * The topology interface allows developers to define DSP topologies in a text
 * file format and to convert the text topology to a binary topology
 * representation that can be understood by the kernel. The topology core
 * currently recognises the following object types :-
 *
 *  * Controls (mixer, enumerated and byte) including TLV data.
 *  * PCMs (Front End DAI & DAI link)
 *  * DAPM widgets
 *  * DAPM graph elements.
 *  * Physical DAI & DAI links
 *  * Private data for each object type.
 *  * Manifest (containing count of each object type)
 *
 * <h3>Topology File Format</h3>
 *
 * The topology text format uses the standard ALSA configuration file format to
 * describe each topology object type. This allows topology objects to include
 * other topology objects as part of their definition. i.e. a TLV data object
 * can be shared amongst many control objects that use the same TLV data.
 *
 *
 * <h4>Controls</h4>
 * Topology audio controls can belong to three different types :-
 *   * Mixer control
 *   * Enumerated control
 *   * Byte control
 *
 * Each control type can contain TLV data, private data, operations and also
 * belong to widget objects.<br>
 *
 * <h5>Control Operations</h5>
 * Driver Kcontrol callback info(), get() and put() operations are mapped with
 * the CTL ops section in topology configuration files. The ctl ops section can
 * assign operations using the standard names (listed below) for the standard
 * kcontrol types or use ID numbers (>256) to map to bespoke driver controls.<br>
 *
 * <pre>
 *
 *      ops."ctl" {
 *              info "volsw"
 *              get "257"
 *              put "257"
 *      }
 *
 * </pre>
 *
 * This mapping shows info() using the standard "volsw" info callback whilst
 * the get() and put() are mapped to bespoke driver callbacks. <br>
 *
 * The Standard operations names for control get(), put() and info calls
 * are :-
 *  * volsw
 *  * volsw_sx
 *  * volsw_xr_sx
 *  * enum
 *  * bytes
 *  * enum_value
 *  * range
 *  * strobe
 *
* <h5>Control Access</h5>
 * Controls access can be specified using the "access" section. If no "access"
 * section is defined then default RW access flags are set for normal and TLV
 * controls.
 *
 * <pre>
 *      access [
 *              read
 *              write
 *              tlv_command
 *      ]
 * </pre>
 *
 * The standard access flags are as follows :-
 *  * read
 *  * write
 *  * read_write
 *  * volatile
 *  * timestamp
 *  * tlv_read
 *  * tlv_write
 *  * tlv_read_write
 *  * tlv_command
 *  * inactive
 *  * lock
 *  * owner
 *  * tlv_callback
 *  * user
 *
 * <h5>Control TLV Data</h5>
 * Controls can also use TLV data to represent dB information. This can be done
 * by defining a TLV section and using the TLV section within the control.
 * The TLV data for DBScale types are defined as follows :-
 *
 * <pre>
 *      scale {
 *              min "-9000"
 *              step "300"
 *              mute "1"
 *      }
 * </pre>
 *
 * Where the meanings and values for min, step and mute are exactly the same
 * as defined in driver code.
 *
 * <h5>Control Channel Mapping</h5>
 * Controls can also specify which channels they are mapped with. This is useful
 * for userspace as it allows applications to determine the correct control
 * channel for Left and Right etc. Channel maps are defined as follows :-
 *
 * <pre>
 *      channel."name" {
 *              reg "0"
 *              shift "0"
 *      }
 * </pre>
 *
 * The channel map reg is the register offset for the control, shift is the
 * bit shift within the register for the channel and the section name is the
 * channel name and can be one of the following :-
 *
 * <pre>
 *  * mono              # mono stream
 *  * fl                # front left
 *  * fr                # front right
 *  * rl                # rear left
 *  * rr                # rear right
 *  * fc                # front center
 *  * lfe               # LFE
 *  * sl                # side left
 *  * sr                # side right
 *  * rc                # rear center
 *  * flc               # front left center
 *  * frc               # front right center
 *  * rlc               # rear left center
 *  * rrc               # rear right center
 *  * flw               # front left wide
 *  * frw               # front right wide
 *  * flh               # front left high
 *  * fch               # front center high
 *  * frh               # front right high
 *  * tc                # top center
 *  * tfl               # top front left
 *  * tfr               # top front right
 *  * tfc               # top front center
 *  * trl               # top rear left
 *  * trr               # top rear right
 *  * trc               # top rear center
 *  * tflc              # top front left center
 *  * tfrc              # top front right center
 *  * tsl               # top side left
 *  * tsr               # top side right
 *  * llfe              # left LFE
 *  * rlfe              # right LFE
 *  * bc                # bottom center
 *  * blc               # bottom left center
 *  * brc               # bottom right center
 * </pre>
 *
 *  <h5>Control Private Data</h5>
 * Controls can also have private data. This can be done by defining a private
 * data section and including the section within the control. The private data
 * section is defined as follows :-
 *
 * <pre>
 * SectionData."pdata for EQU1" {
 *      file "/path/to/file"
 *      bytes "0x12,0x34,0x56,0x78"
 *      shorts "0x1122,0x3344,0x5566,0x7788"
 *      words "0xaabbccdd,0x11223344,0x66aa77bb,0xefef1234"
 *      tuples "section id of the vendor tuples"
 * };
 * </pre>
 * The file, bytes, shorts, words and tuples keywords are all mutually
 * exclusive as the private data should only be taken from one source.
 * The private data can either be read from a separate file or defined in
 * the topology file using the bytes, shorts, words or tuples keywords.
 * The keyword tuples is to define vendor specific tuples. Please refer to
 * section Vendor Tokens and Vendor tuples.
 *
 * It's easy to use a vendor tuples object to define a C structure instance.
 * And a data section can include multiple vendor tuples objects:
 *
 * <pre>
 * SectionData."data element name" {
 *      index "1"       #Index number
 *      tuples [
 *              "id of the 1st vendor tuples section"
 *              "id of the 2nd vendor tuples section"
 *              ...
 *      ]
 * };
 * </pre>
 *
 * <h5>How to define an element with private data</h5>
 * An element can refer to a single data section or multiple data
 * sections.
 *
 * <h6>To refer to a single data section:</h6>
 * <pre>
 * Sectionxxx."element name" {
 *    ...
 *      data "name of data section"             # optional private data
 * }
 * </pre>
 *
 * <h6>To refer to multiple data sections:</h6>
 * <pre>
 * Sectionxxx."element name" {
 *      ...
 *      data [                                          # optional private data
 *              "name of 1st data section"
 *              "name of 2nd data section"
 *              ...
 *      ]
 * }
 * </pre>
 * And data of these sections will be merged in the same order as they are
 * in the list, as the element's private data for kernel.
 *
 * </pre>
 *
 *  <h6>Vendor Tokens</h6>
 * A vendor token list is defined as a new section. Each token element is
 * a pair of string ID and integer value. And both the ID and value are
 * vendor-specific.
 *
 * <pre>
 * SectionVendorTokens."id of the vendor tokens" {
 *      comment "optional comments"
 *      VENDOR_TOKEN_ID1 "1"
 *      VENDOR_TOKEN_ID2 "2"
 *      VENDOR_TOKEN_ID3 "3"
 *      ...
 * }
 * </pre>
 *
 *  <h6>Vendor Tuples</h6>
 * Vendor tuples are defined as a new section. It contains a reference to
 * a vendor token list and several tuple arrays.
 * All arrays share a vendor token list, defined by the tokens keyword.
 * Each tuple array is for a specific type, defined by the string following
 * the tuples keyword. Supported types are: string, uuid, bool, byte,
 * short and word.
 *
 * <pre>
 * SectionVendorTuples."id of the vendor tuples" {
 *      tokens "id of the vendor tokens"
 *
 *      tuples."string" {
 *              VENDOR_TOKEN_ID1 "character string"
 *              ...
 *      }
 *
 *      tuples."uuid" {                 # 16 characters separated by commas
 *              VENDOR_TOKEN_ID2 "0x01,0x02,...,0x0f"
 *              ...
 *      }
 *
 *      tuples."bool" {
 *              VENDOR_TOKEN_ID3 "true/false"
 *              ...
 *      }
 *
 *      tuples."byte" {
 *              VENDOR_TOKEN_ID4 "0x11"
 *              VENDOR_TOKEN_ID5 "0x22"
 *              ...
 *      }
 *
 *      tuples."short" {
 *              VENDOR_TOKEN_ID6 "0x1122"
 *              VENDOR_TOKEN_ID7 "0x3344"
 *              ...
 *      }
 *
 *      tuples."word" {
 *              VENDOR_TOKEN_ID8 "0x11223344"
 *              VENDOR_TOKEN_ID9 "0x55667788"
 *              ...
 *      }
 * }
 * </pre>
 * To define multiple vendor tuples of same type, please append some
 * characters after the type string ("string", "uuid", "bool", "byte", "short"
 * or "word"), to avoid ID duplication in the SectionVendorTuples.<br>
 * The parser will check the first few characters in ID to get the tuple type.
 * Here is an example:
 * <pre>
 * SectionVendorTuples."id of the vendor tuples" {
 *    ...
 *      tuples."word.module0" {
 *              VENDOR_TOKEN_PARAM_ID1 "0x00112233"
 *              VENDOR_TOKEN_PARAM_ID2 "0x44556677"
 *              ...
 *      }
 *
 *      tuples."word.module2" {
 *              VENDOR_TOKEN_PARAM_ID1 "0x11223344"
 *              VENDOR_TOKEN_PARAM_ID2 "0x55667788"
 *              ...
 *      }
 *      ...
 * }
 *
 * </pre>
 *
 * <h5>Mixer Controls</h5>
 * A mixer control is defined as a new section that can include channel mapping,
 * TLV data, callback operations and private data. The mixer section also
 * includes a few other config options that are shown here :-
 *
 * <pre>
 * SectionControlMixer."mixer name" {
 *      comment "optional comments"
 *
 *      index "1"                       # Index number
 *
 *      channel."name" {                # Channel maps
 *         ....
 *      }
 *
 *      ops."ctl" {                     # Ops callback functions
 *         ....
 *      }
 *
 *      max "32"                        # Max control value
 *      invert "0"                      # Whether control values are inverted
 *
 *      tlv "tld_data"                  # optional TLV data
 *
 *      data "pdata for mixer1"         # optional private data
 * }
 * </pre>
 *
 * The section name is used to define the mixer name. The index number can be
 * used to identify topology objects groups(index "0" is common, fit for all
 * user cases).This allows driver operations on objects with index number N and
 * can be used to add/remove pipelines of objects whilst other objects are
 * unaffected.
 *
 * <h5>Byte Controls</h5>
 * A byte control is defined as a new section that can include channel mapping,
 * TLV data, callback operations and private data. The bytes section also
 * includes a few other config options that are shown here :-
 *
 * <pre>
 * SectionControlBytes."name" {
 *      comment "optional comments"
 *
 *      index "1"                       # Index number
 *
 *      channel."name" {                # Channel maps
 *         ....
 *      }
 *
 *      ops."ctl" {                     # Ops callback functions
 *         ....
 *      }
 *
 *      base "0"                        # Register base
 *      num_regs "16"                   # Number of registers
 *      mask "0xff"                     # Mask
 *      max "255"                       # Maximum value
 *
 *      tlv "tld_data"                  # optional TLV data
 *
 *      data "pdata for mixer1"         # optional private data
 * }
 * </pre>
 *
 * <h5>Enumerated Controls</h5>
 * A enumerated control is defined as a new section (like mixer and byte) that
 * can include channel mapping, callback operations, private data and
 * text strings to represent the enumerated control options.<br>
 *
 * The text strings for the enumerated controls are defined in a separate
 * section as follows :-
 *
 * <pre>
 * SectionText."name" {
 *
 *              Values [
 *                      "value1"
 *                      "value2"
                        "value3"
 *              ]
 * }
 * </pre>
 *
 * All the enumerated text values are listed in the values list.<br>
 * The enumerated control is similar to the other controls and defined as
 * follows :-
 *
 * <pre>
 * SectionControlMixer."name" {
 *      comment "optional comments"
 *
 *      index "1"                       # Index number
 *
 *      texts "EQU1"                    # Enumerated text items
 *
 *      channel."name" {                # Channel maps
 *         ....
 *      }
 *
 *      ops."ctl" {                     # Ops callback functions
 *         ....
 *      }
 *
 *      data "pdata for mixer1"         # optional private data
 * }
 * </pre>
 *
 * <h4>DAPM Graph</h4>
 * DAPM graphs can easily be defined using the topology file. The format is
 * very similar to the DAPM graph kernel format. :-
 *
 * <pre>
 * SectionGraph."dsp" {
 *      index "1"                       # Index number
 *
 *      lines [
 *              "sink1, control, source1"
 *              "sink2, , source2"
 *      ]
 * }
 * </pre>
 *
 * The lines in the graph are defined as a variable size list of sinks,
 * controls and sources. The control name is optional as some graph lines have
 * no associated controls. The section name can be used to differentiate the
 * graph with other graphs, it's not used by the kernel atm.
 *
 * <h4>DAPM Widgets</h4>
 * DAPM widgets are similar to controls in that they can include many other
 * objects. Widgets can contain private data, mixer controls and enum controls.
 *
 * The following widget types are supported and match the driver types :-
 *
 *  * input
 *  * output
 *  * mux
 *  * mixer
 *  * pga
 *  * out_drv
 *  * adc
 *  * dac
 *  * switch
 *  * pre
 *  * post
 *  * aif_in
 *  * aif_out
 *  * dai_in
 *  * dai_out
 *  * dai_link
 *
 * Widgets are defined as follows :-
 *
 * <pre>
 * SectionWidget."name" {
 *
 *      index "1"                       # Index number
 *
 *      type "aif_in"                   # Widget type - detailed above
 *      stream_name "name"              # Stream name
 *
 *      no_pm "true"                    # No PM control bit.
 *      reg "20"                        # PM bit register offset
 *      shift "0"                       # PM bit register shift
 *      invert "1                       # PM bit is inverted
 *      subseq "8"                      # subsequence number
 *
 *      event_type "1"                  # DAPM widget event type
 *      event_flags "1"                 # DAPM widget event flags
 *
 *      mixer "name"                    # Optional Mixer Control
 *      enum "name"                     # Optional Enum Control
 *
 *      data "name"                     # optional private data
 * }
 * </pre>
 *
 * The section name is the widget name. The mixer and enum fields are mutually
 * exclusive and used to include controls into the widget. The index and data
 * fields are the same for widgets as they are for controls whilst the other
 * fields map on very closely to the driver widget fields.
 *
 * <h5>Widget Private Data</h5>
 * Widget can have private data. For the format of the private data, please
 * refer to section Control Private Data.
 *
 * <h4>PCM Capabilities</h4>
 * Topology can also define the PCM capabilities of front end or physical DAIs.
 * Capabilities can be defined with the following section :-
 *
 * <pre>
 * SectionPCMCapabilities."name" {
 *
 *      formats "S24_LE,S16_LE"         # Supported formats
 *      rates "48000"                   # Supported rates
 *      rate_min "48000"                # Max supported sample rate
 *      rate_max "48000"                # Min supported sample rate
 *      channels_min "2"                # Min number of channels
 *      channels_max "2"                # max number of channels
 * }
 * </pre>
 * The supported formats use the same naming convention as the driver macros.
 * The PCM capabilities name can be referred to and included by PCM and
 * physical DAI sections.
 *
 * <h4>PCM Configurations</h4>
 * PCM runtime configurations can be defined for playback and capture stream
 * directions with the following section  :-
 *
 * <pre>
 * SectionPCMConfig."name" {
 *
 *      config."playback" {             # playback config
 *              format "S16_LE"         # playback format
 *              rate "48000"            # playback sample rate
 *              channels "2"            # playback channels
 *              tdm_slot "0xf"          # playback TDM slot
 *      }
 *
 *      config."capture" {              # capture config
 *              format "S16_LE"         # capture format
 *              rate "48000"            # capture sample rate
 *              channels "2"            # capture channels
 *              tdm_slot "0xf"          # capture TDM slot
 *      }
 * }
 * </pre>
 *
 * The supported formats use the same naming convention as the driver macros.
 * The PCM configuration name can be referred to and included by PCM and
 * physical link sections.
 *
 * <h4>PCM (Front-end DAI & DAI link) </h4>
 * PCM sections define the supported capabilities and configurations for
 * supported playback and capture streams, names and flags for front end
 * DAI & DAI links. Topology kernel driver will use a PCM object to create
 * a pair of FE DAI & DAI links.
 *
 * <pre>
 * SectionPCM."name" {
 *
 *      index "1"                       # Index number
 *
 *      id "0"                          # used for binding to the PCM
 *
 *      dai."name of front-end DAI" {
 *              id "0"          # used for binding to the front-end DAI
 *      }
 *
 *      pcm."playback" {
 *              capabilities "capabilities1"    # capabilities for playback
 *
 *              configs [               # supported configs for playback
 *                      "config1"
 *                      "config2"
 *              ]
 *      }
 *
 *      pcm."capture" {
 *              capabilities "capabilities2"    # capabilities for capture
 *
 *              configs [               # supported configs for capture
 *                      "config1"
 *                      "config2"
 *                      "config3"
 *              ]
 *      }
 *
 *      # Optional boolean flags
 *      symmetric_rates                 "true"
 *      symmetric_channels              "true"
 *      symmetric_sample_bits           "false"
 *
 *      data "name"                     # optional private data
 * }
 * </pre>
 *
 * <h4>Physical DAI Link Configurations</h4>
 * The runtime configurations of a physical DAI link can be defined by
 * SectionLink. <br> Backend DAI links belong to physical links, and can
 * be configured by either SectionLink or SectionBE, with same syntax.
 * But SectionBE is deprecated atm since the internal processing is
 * actually same.
 *
 * <pre>
 * SectionLink."name" {
 *
 *      index "1"                       # Index number
 *
 *      id "0"                          # used for binding to the link
 *
 *      stream_name "name"              # used for binding to the link
 *
 *      hw_configs [    # runtime supported HW configurations, optional
 *              "config1"
 *              "config2"
 *              ...
 *      ]
 *
 *      default_hw_conf_id "1"          #default HW config ID for init
 *
 *      # Optional boolean flags
 *      symmetric_rates                 "true"
 *      symmetric_channels              "false"
 *      symmetric_sample_bits           "true"
 *
 *      data "name"                     # optional private data
 * }
 * </pre>
 *
 * A physical link can refer to multiple runtime supported hardware
 * configurations, which is defined by SectionHWConfig.
 *
 * <pre>
 * SectionHWConfig."name" {
 *
 *      id "1"                          # used for binding to the config
 *      format "I2S"                    # physical audio format.
 *      bclk   "master"                 # Platform is master of bit clock
 *      fsync  "slave"                  # Platform is slave of fsync
 * }
 * </pre>
 *
 * <h4>Physical DAI</h4>
 * A physical DAI (e.g. backend DAI for DPCM) is defined as a new section
 * that can include a unique ID, playback and capture stream capabilities,
 * optional flags, and private data. <br>
 * Its PCM stream capablities are same as those for PCM objects,
 * please refer to section 'PCM Capabilities'.
 *
 * <pre>
 * SectionDAI."name" {
 *
 *      index "1"                       # Index number
 *
 *      id "0"                          # used for binding to the Backend DAI
 *
 *      pcm."playback" {
 *              capabilities "capabilities1"    # capabilities for playback
 *      }
 *
 *      pcm."capture" {
 *              capabilities "capabilities2"    # capabilities for capture
 *      }
 *
 *      symmetric_rates "true"                  # optional flags
 *      symmetric_channels "true"
 *      symmetric_sample_bits "false"
 *
 *      data "name"                     # optional private data
 * }
 * </pre>
 *
 * <h4>Manifest Private Data</h4>
 * Manfiest may have private data. Users need to define a manifest section
 * and add the references to 1 or multiple data sections. Please refer to
 * section 'How to define an element with private data'. <br>
 * And the text conf file can have at most 1 manifest section. <br><br>
 *
 * Manifest section is defined as follows :-
 *
 * <pre>
 * SectionManifest"name" {
 *
 *      data "name"                     # optional private data
 * }
 * </pre>
 *
 * <h4>Include other files</h4>
 * Users may include other files in a text conf file via alsaconf syntax
 * <path/to/configuration-file>. This allows users to define common info
 * in separate files (e.g. vendor tokens, tuples) and share them for
 * different platforms, thus save the total size of config files. <br>
 * Users can also specifiy additional configuraiton directories relative
 * to "/usr/share/alsa/" to search the included files,  via alsaconf syntax
 * <searchfdir:/relative-path/to/usr/share/alsa>. <br><br>
 *
 * For example, file A and file B are two text conf files for platform X,
 * they will be installed to /usr/share/alsa/topology/platformx. If we
 * need file A to include file B, in file A we can add: <br>
 *
 * <searchdir:topology/platformx> <br>
 * <name-of-file-B> <br><br>
 *
 * ALSA conf will search and open an included file in the following order
 * of priority:
 *  1. directly open the file by its name;
 *  2. search for the file name in "/usr/share/alsa";
 *  3. search for the file name in user specified subdirectories under
 *     "/usr/share/alsa".
 *
 * The order of the included files need not to be same as their
 * dependencies, since the topology library will load them all before
 * parsing their dependencies. <br>
 *
 * The configuration directories defined by a file will only be used to search
 * the files included by this file.
 */

/** Maximum number of channels supported in one control */
#define SND_TPLG_MAX_CHAN               8

/** Topology context */
typedef struct snd_tplg snd_tplg_t;

/** Topology object types */
enum snd_tplg_type {
        SND_TPLG_TYPE_TLV = 0,          /*!< TLV Data */
        SND_TPLG_TYPE_MIXER,            /*!< Mixer control*/
        SND_TPLG_TYPE_ENUM,             /*!< Enumerated control */
        SND_TPLG_TYPE_TEXT,             /*!< Text data */
        SND_TPLG_TYPE_DATA,             /*!< Private data */
        SND_TPLG_TYPE_BYTES,            /*!< Byte control */
        SND_TPLG_TYPE_STREAM_CONFIG,    /*!< PCM Stream configuration */
        SND_TPLG_TYPE_STREAM_CAPS,      /*!< PCM Stream capabilities */
        SND_TPLG_TYPE_PCM,              /*!< PCM stream device */
        SND_TPLG_TYPE_DAPM_WIDGET,      /*!< DAPM widget */
        SND_TPLG_TYPE_DAPM_GRAPH,       /*!< DAPM graph elements */
        SND_TPLG_TYPE_BE,               /*!< BE DAI link */
        SND_TPLG_TYPE_CC,               /*!< Hostless codec <-> codec link */
        SND_TPLG_TYPE_MANIFEST,         /*!< Topology manifest */
        SND_TPLG_TYPE_TOKEN,            /*!< Vendor tokens */
        SND_TPLG_TYPE_TUPLE,            /*!< Vendor tuples */
        SND_TPLG_TYPE_LINK,             /*!< Physical DAI link */
        SND_TPLG_TYPE_HW_CONFIG,        /*!< Link HW config */
        SND_TPLG_TYPE_DAI,              /*!< Physical DAI */
};

/** Fit for all user cases */
#define SND_TPLG_INDEX_ALL  0

/**
 * \brief Create a new topology parser instance.
 * \return New topology parser instance
 */
snd_tplg_t *snd_tplg_new(void);

/**
 * \brief Free a topology parser instance.
 * \param tplg Topology parser instance
 */
void snd_tplg_free(snd_tplg_t *tplg);

/**
 * \brief Parse and build topology text file into binary file.
 * \param tplg Topology instance.
 * \param infile Topology text input file to be parsed
 * \param outfile Binary topology output file.
 * \return Zero on success, otherwise a negative error code
 */
int snd_tplg_build_file(snd_tplg_t *tplg, const char *infile,
                        const char *outfile);

/**
 * \brief Enable verbose reporting of binary file output
 * \param tplg Topology Instance
 * \param verbose Enable verbose output level if non zero
 */
void snd_tplg_verbose(snd_tplg_t *tplg, int verbose);

/** \struct snd_tplg_tlv_template
 * \brief Template type for all TLV objects.
 */
struct snd_tplg_tlv_template {
        int type;        /*!< TLV type SNDRV_CTL_TLVT_ */
};

/** \struct snd_tplg_tlv_dbscale_template
 * \brief Template type for TLV Scale objects.
 */
struct snd_tplg_tlv_dbscale_template {
        struct snd_tplg_tlv_template hdr;       /*!< TLV type header */
        int min;                        /*!< dB minimum value in 0.1dB */
        int step;                       /*!< dB step size in 0.1dB */
        int mute;                       /*!< is min dB value mute ? */
};

/** \struct snd_tplg_channel_template
 * \brief Template type for single channel mapping.
 */
struct snd_tplg_channel_elem {
        int size;       /*!< size in bytes of this structure */
        int reg;        /*!< channel control register */
        int shift;      /*!< channel shift for control bits */
        int id;         /*!< ID maps to Left, Right, LFE etc */
};

/** \struct snd_tplg_channel_map_template
 * \brief Template type for channel mapping.
 */
struct snd_tplg_channel_map_template {
        int num_channels;       /*!< number of channel mappings */
        struct snd_tplg_channel_elem channel[SND_TPLG_MAX_CHAN];        /*!< mapping */
};

/** \struct snd_tplg_pdata_template
 * \brief Template type for private data objects.
 */
struct snd_tplg_pdata_template {
        unsigned int length;    /*!< data length */
        const void *data;       /*!< data */
};

/** \struct snd_tplg_io_ops_template
 * \brief Template type for object operations mapping.
 */
struct snd_tplg_io_ops_template {
        int get;        /*!< get callback ID */
        int put;        /*!< put callback ID */
        int info;       /*!< info callback ID */
};

/** \struct snd_tplg_ctl_template
 * \brief Template type for control objects.
 */
struct snd_tplg_ctl_template {
        int type;               /*!< Control type */
        const char *name;       /*!< Control name */
        int access;             /*!< Control access */
        struct snd_tplg_io_ops_template ops;    /*!< operations */
        struct snd_tplg_tlv_template *tlv; /*!< non NULL means we have TLV data */
};

/** \struct snd_tplg_mixer_template
 * \brief Template type for mixer control objects.
 */
struct snd_tplg_mixer_template {
        struct snd_tplg_ctl_template hdr;       /*!< control type header */
        struct snd_tplg_channel_map_template *map;      /*!< channel map */
        int min;        /*!< min value for mixer */
        int max;        /*!< max value for mixer */
        int platform_max;       /*!< max value for platform control */
        int invert;     /*!< whether controls bits are inverted */
        struct snd_soc_tplg_private *priv;      /*!< control private data */
};

/** \struct snd_tplg_enum_template
 * \brief Template type for enumerated control objects.
 */
struct snd_tplg_enum_template {
        struct snd_tplg_ctl_template hdr;       /*!< control type header */
        struct snd_tplg_channel_map_template *map;      /*!< channel map */
        int items;      /*!< number of enumerated items in control */
        int mask;       /*!< register mask size */
        const char **texts;     /*!< control text items */
        const int **values;     /*!< control value items */
        struct snd_soc_tplg_private *priv;      /*!< control private data */
};

/** \struct snd_tplg_bytes_template
 * \brief Template type for TLV Scale objects.
 */
struct snd_tplg_bytes_template {
        struct snd_tplg_ctl_template hdr;       /*!< control type header */
        int max;                /*!< max byte control value */
        int mask;               /*!< byte control mask */
        int base;               /*!< base register */
        int num_regs;           /*!< number of registers */
        struct snd_tplg_io_ops_template ext_ops;        /*!< ops mapping */
        struct snd_soc_tplg_private *priv;      /*!< control private data */
};

/** \struct snd_tplg_graph_elem
 * \brief Template type for single DAPM graph element.
 */
struct snd_tplg_graph_elem {
        const char *src;        /*!< source widget name */
        const char *ctl;        /*!< control name or NULL if no control */
        const char *sink;       /*!< sink widget name */
};

/** \struct snd_tplg_graph_template
 * \brief Template type for array of DAPM graph elements.
 */
struct snd_tplg_graph_template {
        int count;              /*!< Number of graph elements */
        struct snd_tplg_graph_elem elem[0];     /*!< graph elements */
};

/** \struct snd_tplg_widget_template
 * \brief Template type for DAPM widget objects.
 */
struct snd_tplg_widget_template {
        int id;                 /*!< SND_SOC_DAPM_CTL */
        const char *name;       /*!< widget name */
        const char *sname;      /*!< stream name (certain widgets only) */
        int reg;                /*!< negative reg = no direct dapm */
        int shift;              /*!< bits to shift */
        int mask;               /*!< non-shifted mask */
        int subseq;             /*!< sort within widget type */
        unsigned int invert;            /*!< invert the power bit */
        unsigned int ignore_suspend;    /*!< kept enabled over suspend */
        unsigned short event_flags;     /*!< PM event sequence flags */
        unsigned short event_type;      /*!< PM event sequence type */
        struct snd_soc_tplg_private *priv;      /*!< widget private data */
        int num_ctls;                   /*!< Number of controls used by widget */
        struct snd_tplg_ctl_template *ctl[0];   /*!< array of widget controls */
};

/** \struct snd_tplg_stream_template
 * \brief Stream configurations.
 */
struct snd_tplg_stream_template {
        const char *name;       /*!< name of the stream config */
        int format;             /*!< SNDRV_PCM_FMTBIT_* */
        int rate;               /*!< SNDRV_PCM_RATE_* */
        int period_bytes;       /*!< size of period in bytes */
        int buffer_bytes;       /*!< size of buffer in bytes. */
        int channels;           /*!< number of channels */
};

/** \struct snd_tplg_stream_caps_template
 * \brief Stream Capabilities.
 */
struct snd_tplg_stream_caps_template {
        const char *name;       /*!< name of the stream caps */
        uint64_t formats;       /*!< supported formats SNDRV_PCM_FMTBIT_* */
        unsigned int rates;     /*!< supported rates SNDRV_PCM_RATE_* */
        unsigned int rate_min;  /*!< min rate */
        unsigned int rate_max;  /*!< max rate */
        unsigned int channels_min;      /*!< min channels */
        unsigned int channels_max;      /*!< max channels */
        unsigned int periods_min;       /*!< min number of periods */
        unsigned int periods_max;       /*!< max number of periods */
        unsigned int period_size_min;   /*!< min period size bytes */
        unsigned int period_size_max;   /*!< max period size bytes */
        unsigned int buffer_size_min;   /*!< min buffer size bytes */
        unsigned int buffer_size_max;   /*!< max buffer size bytes */
        unsigned int sig_bits;          /*!< number of bits of content */
};

/** \struct snd_tplg_pcm_template
 * \brief Template type for PCM (FE DAI & DAI links).
 */
struct snd_tplg_pcm_template {
        const char *pcm_name;   /*!< PCM stream name */
        const char *dai_name;   /*!< DAI name */
        unsigned int pcm_id;    /*!< unique ID - used to match */
        unsigned int dai_id;    /*!< unique ID - used to match */
        unsigned int playback;  /*!< supports playback mode */
        unsigned int capture;   /*!< supports capture mode */
        unsigned int compress;  /*!< 1 = compressed; 0 = PCM */
        struct snd_tplg_stream_caps_template *caps[2]; /*!< playback & capture for DAI */
        unsigned int flag_mask; /*!< bitmask of flags to configure */
        unsigned int flags;     /*!< flag value SND_SOC_TPLG_LNK_FLGBIT_* */
        struct snd_soc_tplg_private *priv;      /*!< private data */
        int num_streams;        /*!< number of supported configs */
        struct snd_tplg_stream_template stream[0]; /*!< supported configs */
};

/** \struct snd_tplg_hw_config_template
* \brief Template type to describe a physical link runtime supported
* hardware config, i.e. hardware audio formats.
*/
struct snd_tplg_hw_config_template {
        int id;                         /* unique ID - - used to match */
        unsigned int fmt;               /* SND_SOC_DAI_FORMAT_ format value */
        unsigned char clock_gated;      /* SND_SOC_TPLG_DAI_CLK_GATE_ value */
        unsigned char  invert_bclk;     /* 1 for inverted BCLK, 0 for normal */
        unsigned char  invert_fsync;    /* 1 for inverted frame clock, 0 for normal */
        unsigned char  bclk_master;     /* SND_SOC_TPLG_BCLK_ value */
        unsigned char  fsync_master;    /* SND_SOC_TPLG_FSYNC_ value */
        unsigned char  mclk_direction;  /* SND_SOC_TPLG_MCLK_ value */
        unsigned short reserved;        /* for 32bit alignment */
        unsigned int mclk_rate;         /* MCLK or SYSCLK freqency in Hz */
        unsigned int bclk_rate;         /* BCLK freqency in Hz */
        unsigned int fsync_rate;        /* frame clock in Hz */
        unsigned int tdm_slots;         /* number of TDM slots in use */
        unsigned int tdm_slot_width;    /* width in bits for each slot */
        unsigned int tx_slots;          /* bit mask for active Tx slots */
        unsigned int rx_slots;          /* bit mask for active Rx slots */
        unsigned int tx_channels;       /* number of Tx channels */
        unsigned int *tx_chanmap;       /* array of slot number */
        unsigned int rx_channels;       /* number of Rx channels */
        unsigned int *rx_chanmap;       /* array of slot number */
};

/** \struct snd_tplg_dai_template
 * \brief Template type for physical DAI.
 * It can be used to configure backend DAIs for DPCM.
 */
struct snd_tplg_dai_template {
        const char *dai_name;   /*!< DAI name */
        unsigned int dai_id;    /*!< unique ID - used to match */
        unsigned int playback;  /*!< supports playback mode */
        unsigned int capture;   /*!< supports capture mode */
        struct snd_tplg_stream_caps_template *caps[2]; /*!< playback & capture for DAI */
        unsigned int flag_mask; /*!< bitmask of flags to configure */
        unsigned int flags;     /*!< SND_SOC_TPLG_DAI_FLGBIT_* */
        struct snd_soc_tplg_private *priv;      /*!< private data */

};

/** \struct snd_tplg_link_template
 * \brief Template type for physical DAI Links.
 */
struct snd_tplg_link_template {
        const char *name;       /*!< link name, used to match */
        int id; /*!< unique ID - used to match with existing physical links */
        const char *stream_name;        /*!< link stream name, used to match */

        int num_streams;        /*!< number of configs */
        struct snd_tplg_stream_template *stream;       /*!< supported configs */

        struct snd_tplg_hw_config_template *hw_config; /*!< supported HW configs */
        int num_hw_configs;             /* number of hw configs */
        int default_hw_config_id;       /* default hw config ID for init */

        unsigned int flag_mask;         /* bitmask of flags to configure */
        unsigned int flags;             /* SND_SOC_TPLG_LNK_FLGBIT_* flag value */
        struct snd_soc_tplg_private *priv; /*!< private data */
};

/** \struct snd_tplg_obj_template
 * \brief Generic Template Object
 */
typedef struct snd_tplg_obj_template {
        enum snd_tplg_type type;        /*!< template object type */
        int index;              /*!< group index for object */
        int version;            /*!< optional vendor specific version details */
        int vendor_type;        /*!< optional vendor specific type info */
        union {
                struct snd_tplg_widget_template *widget;        /*!< DAPM widget */
                struct snd_tplg_mixer_template *mixer;          /*!< Mixer control */
                struct snd_tplg_bytes_template *bytes_ctl;      /*!< Bytes control */
                struct snd_tplg_enum_template *enum_ctl;        /*!< Enum control */
                struct snd_tplg_graph_template *graph;          /*!< Graph elements */
                struct snd_tplg_pcm_template *pcm;              /*!< PCM elements */
                struct snd_tplg_link_template *link;            /*!< physical DAI Links */
                struct snd_tplg_dai_template *dai;              /*!< Physical DAI */
        };
} snd_tplg_obj_template_t;

/**
 * \brief Register topology template object.
 * \param tplg Topology instance.
 * \param t Template object.
 * \return Zero on success, otherwise a negative error code
 */
int snd_tplg_add_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t);

/**
 * \brief Build all registered topology data into binary file.
 * \param tplg Topology instance.
 * \param outfile Binary topology output file.
 * \return Zero on success, otherwise a negative error code
 */
int snd_tplg_build(snd_tplg_t *tplg, const char *outfile);

/**
 * \brief Attach private data to topology manifest.
 * \param tplg Topology instance.
 * \param data Private data.
 * \param len Length of data in bytes.
 * \return Zero on success, otherwise a negative error code
 */
int snd_tplg_set_manifest_data(snd_tplg_t *tplg, const void *data, int len);

/**
 * \brief Set an optional vendor specific version number.
 * \param tplg Topology instance.
 * \param version Vendor specific version number.
 * \return Zero on success, otherwise a negative error code
 */
int snd_tplg_set_version(snd_tplg_t *tplg, unsigned int version);

/* \} */

#ifdef __cplusplus
}
#endif

#endif /* __ALSA_TOPOLOGY_H */
